#include "utils.h"
#include <string>
#include <sstream>
namespace dymy
{
    std::vector<std::string> split(const std::string &ss, const std::string &s) noexcept
    {
        using std::string;
        using std::vector;

        vector<string> result;
        const auto s_l = s.length();
        size_t start_index = 0;

        size_t end_index;
        while ((end_index = ss.find(s, start_index)) != std::string::npos)
        {
            string str = ss.substr(start_index, end_index - start_index);
            if (str.length() > 0)
            {
                result.push_back(std::move(str));
            }
            start_index = end_index + s_l;
        }
        if (start_index < ss.length())
        {
            string str = ss.substr(start_index, end_index - start_index);
            if (str.length() > 0)
            {
                result.push_back(std::move(str));
            }
        }
        return result;
    }

    std::optional<int> parse_int(const std::string &input) noexcept
    {
        return std::stoi(input);
    }

    std::optional<int> parse_color(const std::string &value) noexcept
    {
        if (value.find("rgba") != std::string::npos)
        {
            auto start = value.find_first_of('(') + 1;
            auto end = value.find_last_of(')');
            std::string values = value.substr(start, end-start);
            auto v = split(values, ",");
            int r = std::stoi(v[0]);
            int g = std::stoi(v[1]);
            int b = std::stoi(v[2]);
            int a = static_cast<int>(std::stof(v[3]) * 255);
            return (a << 24) | (r << 16) | (g << 8) | (b << 0);
        }
        auto c = value.find('#');
        if (c != std::string::npos)
        {
            std::string input = value.substr(value.find('#') + 1);
            constexpr int alpha = 0xFF000000;
            int color = std::stoi(input, 0, 16);
            if ((color & alpha) == 0)
            {
                color |= alpha;
            }
            return color;
        }
        return std::nullopt;
    }

    std::string to_color(int color) noexcept
    {
        std::ostringstream ss;
        ss << "0x" << std::hex << color;
        return ss.str();
    }

    std::string trim(const std::string &s) noexcept
    {
        auto len = s.length();
        std::string::size_type st = 0;

        while ((st < len) && (s[st] <= ' '))
        {
            st++;
        }
        while ((st < len) && (s[len - 1] <= ' '))
        {
            len--;
        }
        return ((st > 0) || (len < s.length())) ? s.substr(st, len) : s;
    }
    std::string remove_end_semicolon(const std::string &s) noexcept
    {
        auto p = s.find_last_of(';');
        if (p != std::string::npos)
        {
            return s.substr(0, p);
        }
        return s;
    }

    void string_replace(std::string &source, const std::string &from, const std::string &to)
    {
        std::string newString;
        newString.reserve(source.length()); // avoids a few memory allocations

        std::string::size_type lastPos = 0;
        std::string::size_type findPos;

        while (std::string::npos != (findPos = source.find(from, lastPos)))
        {
            newString.append(source, lastPos, findPos - lastPos);
            newString += to;
            lastPos = findPos + from.length();
        }

        // Care for the rest after last occurrence
        newString += source.substr(lastPos);

        source.swap(newString);
    }
}

// namespace dymy
